package com.ray.ba.security.app.service.impl;


import com.ray.ba.security.app.convertor.SecUserConvertor;
import com.ray.ba.security.app.dto.AuthDto;
import com.ray.ba.security.app.dto.SecUserDto;
import com.ray.ba.security.app.service.AuthService;
import com.ray.ba.security.infra.mapper.SecUserMapper;
import com.ray.ba.security.infra.entity.SecUser;
import com.ray.ba.starter.security.jwt.security.JwtUser;
import com.ray.ba.starter.security.jwt.util.JwtTokenUtil;
import com.ray.ba.starter.web.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * description
 *
 * @author r.shi 2020/02/26 15:46
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    SecUserConvertor secUserConvertor;

    @Autowired
    SecUserMapper secUserMapper;

    @Override
    public Map<String, Object> login(String username, String password) {
        Authentication authentication = null;
        try {
            authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (AuthenticationException e) {
            throw new BaseException("Invalid username/password supplied", HttpStatus.UNPROCESSABLE_ENTITY);
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        JwtUser userDetail = (JwtUser) authentication.getPrincipal();

         String accessToken = jwtTokenUtil.generateTokenWithHead(userDetail);

        SecUserDto secUserDto = new SecUserDto(userDetail);
        return new HashMap<String, Object>(2) {{
            put("token", accessToken);
            put("user", secUserDto);
        }};
    }


    @Override
    public void registry(AuthDto dto) {
        SecUser userByName = secUserMapper.selectOne(SecUser.builder().username(dto.getUsername()).build());
        if(ObjectUtils.isEmpty(userByName)){

            SecUser secUser =   SecUser.builder().username(dto.getUsername()).password(dto.getPassword()).email(dto.getEmail()).sex(dto.getSex()).age(dto.getAge()).build();

            secUser.setPassword(passwordEncoder.encode(dto.getPassword()));
            secUserMapper.insertSelective(secUser);
        } else {
            throw new BaseException("Username is already in use", HttpStatus.UNPROCESSABLE_ENTITY);
        }
    }

    @Override
    public void logout() {
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    @Override
    public SecUserDto info() {
        JwtUser jwtUser = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return new SecUserDto(jwtUser);
    }


}
